# 
# Project: Last.sk
# File: lastsk.py
# Author: Angel Luis Calvo Ortega
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA


#this import statement allows access to the karamba functions
import karamba

import xml.sax
import os
import ConfigParser
import urllib

import profile
import systemrecs
import topartists
import toptracks
import topalbums
import recenttracks

profile_url = 'http://ws.audioscrobbler.com/1.0/user/%s/profile.xml'

WS_URL = 'http://ws.audioscrobbler.com/1.0/user/%s/%s'
VIEWS = (['Top Artists', 'topartists.xml', topartists.TopArtistsHandler(), 0, 0],
         ['Top Tracks', 'toptracks.xml', toptracks.TopTracksHandler(), 0, 0],
         ['Top Albums', 'topalbums.xml', topalbums.TopAlbumsHandler(), 0, 0],
         ['System Recomendations', 'systemrecs.xml', systemrecs.SystemRecsHandler(), 0, 0],
         ['Recent Tracks', 'recenttracks.xml', recenttracks.RecentTracksHandler(), 0, 0])


# Shows a view
def setView(widget):
    global dataText, user, viewIndex
    handler = VIEWS[viewIndex][2]
    if not handler.cached:
        parser = xml.sax.make_parser()
        parser.setContentHandler(handler)
        parser.parse(WS_URL % (user, VIEWS[viewIndex][1]))
    karamba.changeRichText(widget, dataText, handler.toString())
    karamba.setRichTextWidth(widget, dataText, 256)
    karamba.redrawWidget(widget)

# Retrieves and shows user's profile
def setUser(widget):
    global profileText, lastskPath, avatarImage
    parser = xml.sax.make_parser()
    handler = profile.ProfileHandler()
    parser.setContentHandler(handler)
    parser.parse(profile_url % user)
    karamba.changeRichText(widget, profileText, handler.toString())
    karamba.setRichTextWidth(widget, profileText, 192)
    try:
        urllib.urlretrieve(handler.avatar, os.path.join(lastskPath, 'avatar.png'))
        karamba.setImagePath(widget, avatarImage, os.path.join(lastskPath, 'avatar.png'))
        karamba.resizeImage(widget, avatarImage, 64, 64)
    except IOError:
        pass
    setView(widget)
    karamba.redrawWidget(widget)
    
# Gets new user's profile
def changeUser(widget):
    global user, userBox
    newUser = karamba.getInputBoxValue(widget, userBox)
    if newUser != user:
        user = newUser
        setUser(widget)
        clearCaches()

# Clears all cached data of views
def clearCaches():
    for view in VIEWS:
        view[2].clear()

# Clear cached data of actual view
def clearCache():
    global viewIndex
    VIEWS[viewIndex][2].clear()

# Reads config file
def readConfig():
    global user, viewIndex, lastskPath
    config = ConfigParser.RawConfigParser()
    config.read(os.path.join(lastskPath, 'lastsk.conf'))
    if not config.has_section('global'):
        user = ''
        viewIndex = 0
    else:
        user = config.get('global', 'user')
        viewIndex = config.getint('global', 'viewIndex')

# Writes state to file
def writeConfig():
    global user, viewIndex
    config = ConfigParser.RawConfigParser()
    config.add_section('global')
    config.set('global', 'user', user)
    config.set('global', 'viewIndex', viewIndex)
    f = file(os.path.join(lastskPath, 'lastsk.conf'), 'w')
    config.write(f)
    f.close()

#this is called when you widget is initialized
def initWidget(widget):
    global profileText, dataText, avatarImage, userBox
    global leftButton, rightButton, setUserButton, popUpMenu, listButton, refreshButton
    global viewIndex, user, lastskPath
    
    lastskPath = os.path.join(os.environ['HOME'], '.superkaramba/lastsk')
    if not os.path.exists(lastskPath):
        os.mkdir(lastskPath)

    readConfig()

    # Background
    karamba.createBackgroundImage(widget, 0, 0, 'images/bg.png')
    # User input box
    userBox = karamba.createInputBox(widget, 2, 34, 128, 20, user)
    karamba.changeInputBoxFontSize(widget, userBox, 14)
    karamba.changeInputBoxBackgroundColor(widget, userBox, 0xd0, 0x1f, 0x3c)
    # Set user button
    setUserButton = karamba.createImage(widget, 132, 34, 'images/apply.png')
    karamba.attachClickArea(widget, setUserButton, '', '', '')
    karamba.addImageTooltip(widget, setUserButton, 'Set user')
    # Profile text
    profileText = karamba.createRichText(widget, '', False)
    karamba.moveRichText(widget, profileText, 0, 54)
    # Avatar image
    avatarImage = karamba.createImage(widget, 190, 34, '')
    # View text
    dataText = karamba.createRichText(widget, '', False)
    karamba.moveRichText(widget, dataText, 0, 100)
    # Left arrow button
    leftButton = karamba.createImage(widget, 184, 102, 'images/leftarrow.png')
    karamba.attachClickArea(widget, leftButton, '', '', '')
    karamba.addImageTooltip(widget, leftButton, 'Previous view')
    # Right arrow button
    rightButton = karamba.createImage(widget, 202, 102, 'images/rightarrow.png')
    karamba.attachClickArea(widget, rightButton, '', '', '')
    karamba.addImageTooltip(widget, rightButton, 'Next view')
    # Views list button
    listButton = karamba.createImage(widget, 220, 102, 'images/bottom.png')
    karamba.attachClickArea(widget, listButton, '', '', '')
    karamba.addImageTooltip(widget, listButton, 'Views list')
    # Refresh view button
    refreshButton = karamba.createImage(widget, 238, 102, 'images/reload.png')
    karamba.attachClickArea(widget, refreshButton, '', '', '')
    karamba.addImageTooltip(widget, refreshButton, 'Refresh view')

    # Views list popup menu
    popUpMenu = karamba.createMenu(widget)
    for view in VIEWS:
        view[4] = karamba.addMenuItem(widget, popUpMenu, view[0], '')
    # About menu item
    karamba.addMenuConfigOption(widget, 'about', 'About...')
    karamba.setMenuConfigOption(widget, 'about', 0)

    if user != None and user != '':
        setUser(widget)
        #setView(widget)


#This is called when your widget is closed.  You can use this to clean
#up open files, etc.  You don't need to delete text and images in your
#theme.  That is done automatically.  This callback is just for cleaning up
#external things.  Most people don't need to put anything here.
def widgetClosed(widget):
    writeConfig()


#this is called everytime your widget is updated
#the update inverval is specified in the .theme file
def widgetUpdated(widget):
    clearCache()
    setView(widget)


#This gets called everytime our widget is clicked.
#Notes:
#  widget = reference to our widget
#  x = x position (relative to our widget)
#  y = y position (relative to our widget)
#  botton = button clicked:
#                    1 = Left Mouse Button
#                    2 = Middle Mouse Button
#                    3 = Right Mouse Button, but this will never happen
#                        because the right mouse button brings up the
#                        Karamba menu.
#                    4,5 = Scroll wheel up and down
def widgetClicked(widget, x, y, button):
    pass


#This gets called everytime our widget is clicked.
#Notes
#  widget = reference to our widget
#  x = x position (relative to our widget)
#  y = y position (relative to our widget)
#  botton = button being held:
#                    0 = No Mouse Button
#                    1 = Left Mouse Button
#                    2 = Middle Mouse Button
#                    3 = Right Mouse Button, but this will never happen
#                        because the right mouse button brings up the
#                        Karamba menu.
def widgetMouseMoved(widget, x, y, button):
    #Warning:  Don't do anything too intensive here
    #You don't want to run some complex piece of code everytime the mouse moves
    pass


#This gets called when an item is clicked in a popup menu you have created.
#  menu = a reference to the menu
#  id = the number of the item that was clicked.
def menuItemClicked(widget, menu, id):
    global viewIndex
    for i in range(len(VIEWS)):
        if VIEWS[i][4] == id:
            viewIndex = i
            setView(widget)
            break


#This gets called when an item is clicked in the theme CONFIGURATION menu,
#not the popup menus that you create.
#  key = the reference to the configuration key that was changed
#  value = the new value (true or false) that was selected
def menuOptionChanged(widget, key, value):
    if key == 'about':
        karamba.setMenuConfigOption(widget, 'about', 0)
        karamba.execute('kdialog --msgbox "Last.sk 0.1\nAngel Luis Calvo Ortega" --title "About" --caption "Last.sk"')


#This gets called when a meter (image, text, etc) is clicked.
# NOTE you must use attachClickArea() to make a meter
# clickable.  
#  widget = reference to your theme
#  meter = the meter clicked
#  button = the button clicked (see widgetClicked for button numbers)
def meterClicked(widget, meter, button):
    global leftButton, rightButton, setUserButton, listButton, viewIndex
    if button == 1:
        if meter == leftButton:
            viewIndex -= 1
            if viewIndex == -1:
                viewIndex = len(VIEWS) - 1
            setView(widget)
        elif meter == rightButton:
            viewIndex = (viewIndex + 1) % len(VIEWS)
            setView(widget)
        elif meter == setUserButton:
            changeUser(widget)
            setView(widget)
        elif meter == listButton:
            global popUpMenu
            karamba.popupMenu(widget, popUpMenu, 220, 118)
        elif meter == refreshButton:
            clearCache()
            setView(widget)

#This gets called when a command you have executed with executeInteractive() outputs something
#to stdout.  This way you can get the output of for example kdialog without freezing up the widget
#waiting for kdialog to end.
#  widget = reference to your theme
#  pid = process number of the program outputting (use this if you execute more than out process)
#  output = the text the program outputted to stdout
def commandOutput(widget, pid, output):
    pass


#This gets called when an item is dropped on this widget.
# NOTE you have to call acceptDrops() before your widget will accept drops.
#  widget = reference to your theme
#  dropText = the text of the dropped item (probably a URL to it's location in KDE)
def itemDropped(widget, dropText):
    pass


#This gets called when a new program is LOADING in KDE.  When it is done
#loading, startupRemoved() is called, followed by taskAdded().
#  widget = reference to your widget
#  task = A refence to the task that is starting.  
def startupAdded(widget, startup):
    pass


#This gets called when a new program is done LOADING in KDE.
#  widget = reference to your widget
#  task = A refence to the task that just finished loading.  
def startupRemoved(widget, startup):
    pass


#This is called every time a new task (program) is started in KDE.
#  widget = reference to your widget
#  task = A refence to the new task.  Call getTaskInfo() with this reference
#         to get the name, etc of this new task.
def taskAdded(widget, task):
    pass


#This is called everytime a task (program) is closed in KDE.
#  widget = reference to your widget
#  task = A refence to the task.  
def taskRemoved(widget, task):
    pass


#This is called everytime a different task gains focus (IE, the user clicks
#on a different window).  
#  widget = reference to your widget
#  task = A refence to the task.  Call getTaskInfo() with this reference
#         to get the name, etc of this new task.
def activeTaskChanged(widget, task):
    pass

#This is called everytime the systray you created with createSystray() is updated
def systrayUpdated(widget):
    pass

#This is called everytime the current desktop changes
#  widget = reference to your widget
#  desktop = the current desktop
def desktopChanged(widget, desktop):
    pass

#This is called everytime the wallpaper changes on a desktop 
#  widget = reference to your widget
#  desktop = the desktop whose wallpaper changed
def wallpaperChanged(widget, desktop):
    pass

#This is called everytime there is a key press in any focused input field
#  widget = reference to your widget
#  meter = reference to an input box
#  char = the key that was pressed
def keyPressed(widget, meter, char):
    pass

# This will be printed when the widget loads.
print "Last.sk Loaded!"

